parser grammar TestGrammarParser;
options { tokenVocab = TestGrammarLexer; }

@header {
#include <map>
#include <string>
#include <iostream>
}
@parser::members {
std::map<antlr4::ParserRuleContext*, std::string> astmap;
}
module
	: statement + 
	;

statement
	: assign_stmt{ astmap[$assign_stmt.ctx] = "assign_stmt"; } 
	;

assign_stmt
	: variable_access{ astmap[$variable_access.ctx] = "variable_access"; } Assign expression{ astmap[$expression.ctx] = "expression"; } 
	;

variable_access
	: variable_name{ astmap[$variable_name.ctx] = "name_access"; } 
	;

variable_name
	: identifier{ astmap[$identifier.ctx] = "TEXT"; } 
	;

expression
	: add_expr 
	;

add_expr
	locals[
		std::map<std::string, std::vector<antlr4::ParserRuleContext*>> ctxmap, 
		std::map<std::string, std::vector<std::pair<std::string, std::any>>> extra_node_construct
	]
	@init {
		$ctxmap = {
			std::make_pair("expr_param", std::vector<antlr4::ParserRuleContext*>{}), 
		};
	}
	@after {
		$extra_node_construct = {
			{"expr_params", std::vector<std::pair<std::string, std::any>>{
				{"NODES", $ctxmap["expr_param"]},}
			}, };
	}
	: prim_expr | prim_expr{ astmap[$prim_expr.ctx] = "expr_param";$ctxmap["expr_param"].push_back($prim_expr.ctx); } op{ astmap[$op.ctx] = "op"; } add_expr{ astmap[$add_expr.ctx] = "expr_param";$ctxmap["expr_param"].push_back($add_expr.ctx); } 
	;

op
	: addop{ astmap[$addop.ctx] = "ADDOP"; } | subop{ astmap[$subop.ctx] = "SUBOP"; } 
	;

prim_expr
	: variable_access{ astmap[$variable_access.ctx] = "variable_access"; } | LeftParen expression{ astmap[$expression.ctx] = "expression"; } RightParen | literal{ astmap[$literal.ctx] = "literal"; } 
	;

literal
	: number{ astmap[$number.ctx] = "NUMBER"; } 
	;

identifier
	: Identifier 
	;

number
	: INT_LITERAL 
	;

addop
	: ADD 
	;

subop
	: SUB 
	;

